//copy from ngx
#ifndef MSGD_RBTREE_H
#define MSGD_RBTREE_H 1

#include <config.h>
#include <core.h>


typedef msgd_uint_t  msgd_rbtree_key_t;
typedef msgd_int_t   msgd_rbtree_key_int_t;


typedef struct msgd_rbtree_node_s  msgd_rbtree_node_t;

struct msgd_rbtree_node_s {
    msgd_rbtree_key_t       key;
    msgd_rbtree_node_t     *left;
    msgd_rbtree_node_t     *right;
    msgd_rbtree_node_t     *parent;
    u_char                 color;
    u_char                 data;
};


typedef struct msgd_rbtree_s  msgd_rbtree_t;

typedef void (*msgd_rbtree_insert_pt) (msgd_rbtree_node_t *root,
    msgd_rbtree_node_t *node, msgd_rbtree_node_t *sentinel);

struct msgd_rbtree_s {
    msgd_rbtree_node_t     *root;
    msgd_rbtree_node_t     *sentinel;
    msgd_rbtree_insert_pt   insert;
};


#define msgd_rbtree_init(tree, s, i)                                           \
    msgd_rbtree_sentinel_init(s);                                              \
    (tree)->root = s;                                                         \
    (tree)->sentinel = s;                                                     \
    (tree)->insert = i


void msgd_rbtree_insert(msgd_rbtree_t *tree,
    msgd_rbtree_node_t *node);
void msgd_rbtree_delete(msgd_rbtree_t *tree,
    msgd_rbtree_node_t *node);
void msgd_rbtree_insert_value(msgd_rbtree_node_t *root, msgd_rbtree_node_t *node,
    msgd_rbtree_node_t *sentinel);
void msgd_rbtree_insert_timer_value(msgd_rbtree_node_t *root,
    msgd_rbtree_node_t *node, msgd_rbtree_node_t *sentinel);


#define msgd_rbt_red(node)               ((node)->color = 1)
#define msgd_rbt_black(node)             ((node)->color = 0)
#define msgd_rbt_is_red(node)            ((node)->color)
#define msgd_rbt_is_black(node)          (!msgd_rbt_is_red(node))
#define msgd_rbt_copy_color(n1, n2)      (n1->color = n2->color)


/* a sentinel must be black */

#define msgd_rbtree_sentinel_init(node)  msgd_rbt_black(node)


static inline msgd_rbtree_node_t *
msgd_rbtree_min(msgd_rbtree_node_t *node, msgd_rbtree_node_t *sentinel)
{
    while (node->left != sentinel) {
        node = node->left;
    }

    return node;
}


#endif /* MSGD_RBTREE_H */
